package com.whh.downloader;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;
import org.w3c.dom.html.HTMLParagraphElement;

import com.google.gson.Gson;
import com.whh.downloader.model.Ability;
import com.whh.downloader.model.Hero;

public class TgbugHtmlParser {
	
	private static final Logger logger = Logger.getLogger(TgbugHtmlParser.class);
	//private static final String ABILITY_IMG_PATH = "F:\\素材\\tgbus\\abilities\\";
	//private static final String HERO_IMG_PATH = "F:\\素材\\tgbus\\heros\\";
	private static final String HTML_PATH = "F:\\素材\\tgbus\\htmls\\";
	private static final String HERO_JSON_PATH = "F:\\素材\\tgbus\\";
	private static final String ITEM_HTML_PATH = "F:\\素材\\tgbus\\";
	private static final String ITEM_JSON_PATH = "F:\\素材\\tgbus\\";
	
	public static void main(String[] args) {
		exportHerosJson(false);
	}
	
	/**
	 * 导出英雄信息到json
	 */
	public static void exportHerosJson(boolean isDownloadImg){
		List<Hero> heros = new ArrayList<Hero>();
		List<String> urls = getAllHerosLink();
		int i = 0;
		for(String url:urls){
			Hero hero = parseHeroHtml(url,isDownloadImg);
			if(hero==null){
				i++;
			}
			heros.add(hero);
		}
		if(i>0){
			logger.error("解析错误:"+i+"次，需要重新解析");
		}
		try{
			File folder = new File(HERO_JSON_PATH);
			if(!folder.exists()){
				folder.mkdirs();
			}
			File json = new File(HERO_JSON_PATH+"heros.json");
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(json)));
			for(int x=0;x<heros.size();x++){
				bw.write(new Gson().toJson(heros.get(x))+"\n");
			}
			bw.flush();
			bw.close();
			logger.info("导出英雄信息到json["+json.getPath()+"]");
		}catch(Exception e){
			logger.error("导出英雄信息到json出错",e);
		}
	}
	
	/**
	 * 获取所有的HTML路径
	 * @return
	 */
	public static List<String> getAllHerosLink(){
		try{
			List<String> links = new ArrayList<String>();
//			File dir = new File(HTML_PATH);
//			File[] files = dir.listFiles();
//			for(int i=0;i<files.length;i++){
//				links.add(files[i].getPath());
//			}
			Document doc = Jsoup.connect("http://dota2.tgbus.com/heroes/").get();
			Elements hrefs = doc.select("div[class=left heroes] div[class=tavernbody] li a");
			for(Element href:hrefs){
				String url = href.attr("href");
				String name=url.substring(url.indexOf("Special")+8,url.length()-1)+".html";
				links.add(HTML_PATH+name);
				System.out.println(HTML_PATH+name);
			}
			return links;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 下载所需要解析的HTML
	 */
	public static void downloadAllHtml(){
		try{
			Document doc = Jsoup.connect("http://dota2.tgbus.com/heroes/").get();
			Elements hrefs = doc.select("div[class=left heroes] div[class=tavernbody] li a");
			for(Element href:hrefs){
				String url = href.attr("href");
				String name=url.substring(url.indexOf("Special")+8,url.length()-1)+".html";
				ImgDownloader.downloadImg(url, HTML_PATH, name);
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static void downloadItemHtml(){
		String url ="http://dota2.tgbus.com/items/";
		ImgDownloader.downloadImg(url, ITEM_HTML_PATH, "item.html");
	}
	
	/**
	 * 解析英雄
	 * @param link
	 * @param isDownloadImg
	 * @return
	 */
	public static Hero parseHeroHtml(String link,boolean isDownloadImg){
		try{
			//String url=link.replace(HTML_PATH, "http://dota2.tgbus.com/Special/").replace(".html", "")+"/";
			Document doc = Jsoup.parse(new File(link),"gb2312");
			Hero hero = new Hero();
			hero.setLevel(1);
			Element groupAndTypeElement = doc.select("div[class=wrapper-body] div[class=path green]").get(0);
			if(groupAndTypeElement!=null){
				String groupAndType = groupAndTypeElement.text();
				//获取阵营
				if(groupAndType.indexOf("天辉")>0){
					hero.setGroup(Constant.GROUP_RADIANT);
				}else if(groupAndType.indexOf("夜魇")>0){
					hero.setGroup(Constant.GROUP_DIRE);
				}else{
					logger.error("解析英雄阵营出错:"+groupAndType+"|"+link);
				}
				//获取类型
				if(groupAndType.indexOf("智力")>0){
					hero.setType(Constant.HERO_TYPE_INT);
				}else if(groupAndType.indexOf("敏捷")>0){
					hero.setType(Constant.HERO_TYPE_AGI);
				}else if(groupAndType.indexOf("力量")>0){
					hero.setType(Constant.HERO_TYPE_STR);
				}else{
					logger.error("解析英雄类型出错:"+groupAndType+"|"+link);
				}
			}else{
				logger.error("解析英雄类型出错:不存在数据|"+link);
			}
			
			//英文名称、中文名称、简称
			String nameCn = "";
			String nameEn = "";
			Element heroNames = doc.select("div[class=HeroName]").get(0);
			String nameEn1=heroNames.select("h1[class=red] span[class=HeroName2]").get(0).text();
			String nameCn1=heroNames.select("h1[class=red] span[class=HeroName2]").get(0).previousSibling().toString();
			if(heroNames.select("span[class=HeroName1 green] span[class=HeroName2]").size()>0){
				String nameEn2=heroNames.select("span[class=HeroName1 green] span[class=HeroName2]").get(0).text();
				String nameCn2=heroNames.select("span[class=HeroName1 green] span[class=HeroName2]").get(0).previousSibling().toString();
				nameCn=nameCn1+"|"+nameCn2;
				nameEn=nameEn1+"|"+nameEn2;
			}else{
				nameCn=nameCn1;
				nameEn=nameEn1;
				logger.error("不存在第二个中英文名称:"+link);
			}
			String nameShort = "";
			if(heroNames.select("p").size()>0){
				nameShort=heroNames.select("p").get(0).text();
				nameShort = nameShort.substring(nameShort.indexOf("：")+1,nameShort.length());
			}else{
				logger.error("不存在简称:"+link);
			}
			hero.setNameCn(nameCn);
			hero.setNameEn(nameEn.toUpperCase());
			hero.setNameShort(nameShort.toUpperCase());
			
			//背景故事
			String bio = doc.select("div[class=HeroIntro left inline]").get(0).text();
			hero.setBio(bio);
			
			Map<String,String> map = CN2EN.getCN2ENMap().get(nameCn1);
			hero.setRoles(map.get("roles"));
			
			//头像
			//Element header =  doc.select("div[class=HeroAvatar] img").get(0);
			//String headerVert = header.attr("src");
			//hero.setHeaderVert(headerVert.substring(headerVert.indexOf("/")+1,headerVert.indexOf(".")));
			//if(isDownloadImg){
			//	ImgDownloader.downloadImg(url+header.attr("src"), HERO_IMG_PATH,null);
			//}
			hero.setHeaderVert(map.get("headerVert"));
			
			//初始数据
			Element heroAttributes = doc.select("div[class=HeroAttribute left]").get(0);
			Element heroAttributeLeft = heroAttributes.select("div[class=HeroBasicAttribute left] p").get(0);
			String att_str = null;
			String att_agi = null;
			String att_int = null;
			if(hero.getType().equals(Constant.HERO_TYPE_STR)){
				att_str = heroAttributeLeft.select("span[class=red]").get(0).text();
				att_agi = heroAttributeLeft.textNodes().get(0).text();
				att_int = heroAttributeLeft.textNodes().get(1).text();
			}else if(hero.getType().equals(Constant.HERO_TYPE_AGI)){
				att_agi = heroAttributeLeft.select("span[class=red]").get(0).text();
				att_str = heroAttributeLeft.textNodes().get(0).text();
				att_int = heroAttributeLeft.textNodes().get(1).text();
			}else if(hero.getType().equals(Constant.HERO_TYPE_INT)){
				att_int = heroAttributeLeft.select("span[class=red]").get(0).text();
				att_str = heroAttributeLeft.textNodes().get(0).text();
				att_agi = heroAttributeLeft.textNodes().get(1).text();
			}else{
				logger.error("英雄类型出错:"+hero.getType()+"|"+link);
			}
			String att_hp = heroAttributeLeft.textNodes().get(2).text();
			String att_mana = heroAttributeLeft.textNodes().get(3).text();
			String att_defense = heroAttributeLeft.textNodes().get(4).text();
			String att_attack = heroAttributeLeft.textNodes().get(5).text();
			
			Integer str = Integer.parseInt(att_str.split("\\+")[0].trim());
			Double strInc = Double.parseDouble(att_str.split("\\+")[1].trim()); 
			Integer agi = Integer.parseInt(att_agi.split("\\+")[0].trim());
			Double agiInc = Double.parseDouble(att_agi.split("\\+")[1].trim()); 
			Integer int_ = Integer.parseInt(att_int.split("\\+")[0].trim());
			Double intInc = Double.parseDouble(att_int.split("\\+")[1].trim()); 
			Integer hp = Integer.parseInt(att_hp.split("：")[1].trim());
			Integer mana = Integer.parseInt(att_mana.split("：")[1].trim());
			Double defense = Double.parseDouble(att_defense.split("：")[1].trim());
			Integer attackMin = Integer.parseInt(att_attack.split("：")[1].split("\\-")[0].trim());
			Integer attackMax = Integer.parseInt(att_attack.split("：")[1].split("\\-")[1].trim());
			
			hero.setIntelligence(int_);
			hero.setIntelligenceIncrease(intInc);
			hero.setAgility(agi);
			hero.setAgilityIncrease(agiInc);
			hero.setStrength(str);
			hero.setStrengthIncrease(strInc);
			hero.setHp(hp);
			hero.setMana(mana);
			hero.setDefense(defense);
			hero.setAttackMin(attackMin);
			hero.setAttackMax(attackMax);
			
			Element heroAttributeRight = heroAttributes.select("div[class=HeroAttributeFigure left] p").get(0);
			String att_moveSpeed=heroAttributeRight.textNodes().get(0).text();
			String att_sightRange=heroAttributeRight.textNodes().get(1).text();
			String att_attackRange=heroAttributeRight.textNodes().get(2).text();
			String att_missileSpeed=heroAttributeRight.textNodes().get(3).text();
			String att_attackPoint=heroAttributeRight.textNodes().get(4).text();
			String att_castPoint=heroAttributeRight.textNodes().get(5).text();
			String att_attackTime=heroAttributeRight.textNodes().get(6).text();
			
			Integer moveSpeed = Integer.parseInt(att_moveSpeed);
			Integer sightRangeDay = Integer.parseInt(att_sightRange.split("\\/")[0].trim());
			Integer sightRangeNight = Integer.parseInt(att_sightRange.split("\\/")[1].trim());
			Integer attackRange = att_attackRange.equals("近战")?0:Integer.parseInt(att_attackRange);
			Integer missileSpeed = att_missileSpeed.equals("直接")?0:Integer.parseInt(att_missileSpeed);
			Double attackPoint=Double.parseDouble(att_attackPoint.split("[\\+]")[0]);
			Double attackBackswing=Double.parseDouble(att_attackPoint.split("[\\+]")[1]);
			Double castPoint=Double.parseDouble(att_castPoint.split("[\\+]")[0]);
			Double castBackswing=Double.parseDouble(att_castPoint.split("[\\+]")[1]);
			Double attackTime=Double.parseDouble(att_attackTime);
			
			hero.setMoveSpeed(moveSpeed);
			hero.setSightRangeDay(sightRangeDay);
			hero.setSightRangeNight(sightRangeNight);
			hero.setAttackRange(attackRange);
			hero.setMissileSpeed(missileSpeed);
			hero.setAttackPoint(attackPoint);
			hero.setAttackBackswing(attackBackswing);
			hero.setCastPoint(castPoint);
			hero.setCastBackswing(castBackswing);
			hero.setAttackTime(attackTime);
			
			Elements heroSpells = doc.select("#con_one_1 div[class=HeroSpell]");
			List<Ability> abilities = new ArrayList<Ability>();
			String[] abilityImgs = map.get("abilityStr").split(",");
			for(int n=0;n<heroSpells.size();n++){
				Ability ability = new Ability();
				//Element spellAvatar = heroSpells.get(n).select("div[class=SpellAvatar left] img").get(0);
				//String img = spellAvatar.attr("src");
				//ability.setImg(img.substring(img.indexOf("/")+1,img.indexOf(".")));
				//if(isDownloadImg){
				//	ImgDownloader.downloadImg(url+spellAvatar.attr("src"), ABILITY_IMG_PATH, null);
				//}
				ability.setImg(abilityImgs[n]);
				String name = heroSpells.get(n).select("div[class=SpellIntro left] h3").first().text();
				String desc = heroSpells.get(n).select("p[class=SpellDescription]").first().text();
				Elements tipsLis = heroSpells.get(n).select("div[class=SpellTips] li");
				String tips = "";
				for(int y=0;y<tipsLis.size();y++){
					tips = tips+tipsLis.get(y).text();
					if(y!=tipsLis.size()-1){
						tips=tips+"||";
					}
				}
				String effect = "";
				String coolDown = "";
				String manaCost = "";
				if(heroSpells.get(n).select("div[class=HeroAttributeName left] p").size()>0){
					List<TextNode> leftNodes = heroSpells.get(n).select("div[class=HeroAttributeName left] p").first().textNodes();
					List<TextNode> rightNodes = heroSpells.get(n).select("div[class=HeroAttributeFigure left] p").first().textNodes();
					if(leftNodes.size()!=rightNodes.size()){
						logger.error("技能解析出错,name="+name+":"+link);
					}
					for(int x=0;x<leftNodes.size();x++){
						if(leftNodes.get(x).text().equals("魔法消耗：")){
							manaCost=rightNodes.get(x).text();
							continue;
						}
						if(leftNodes.get(x).text().equals("冷却时间：")){
							coolDown=rightNodes.get(x).text();
							continue;
						}
						if(x>rightNodes.size()-1){
							effect=effect+leftNodes.get(x).text()+" ";
						}else{
							effect=effect+leftNodes.get(x).text()+rightNodes.get(x).text();
						}
						if(x!=leftNodes.size()-1){
							effect=effect+"||";
						}
					}
				}
				ability.setCoolDown(coolDown);
				ability.setManaCost(manaCost);
				ability.setDesc(desc);
				ability.setEffect(effect);
				ability.setName(name);
				ability.setTips(tips);
				abilities.add(ability);
			}
			hero.setAbilities(abilities);
			return hero;
		}catch (Exception e) {
			logger.error("解析英雄出错:"+link,e);
			return null;
		}
	}
	
}
